Projet Zuul de conception orientée objet en Java d'un jeu d'aventure
Forum des exercices du projet Zuul
Exercice 7.18.5
Cet exercice est considéré OPTIONNEL tant que vous n'arrivez pas à l'exercice 7.46. Pour l'instant, passez à l'exercice suivant.
Les objets Room du jeu ne sont accessibles que dans createRooms.
Pour y avoir accès depuis n'importe quelle méthode ou classe (notamment au 7.46), créer un tableau (ou une ArrayList ou une HashMap *) contenant toutes les Room (numérotées ou associées à leur nom).
Il suffira alors de le (ou la) passer en paramètre, en cas de besoin (notamment au 7.46).
Réfléchissez à l'endroit où vous allez créer ce tableau/liste/hashmap * : vous devrez lui ajouter toutes vos pièces, encore faut-il y avoir accès ...
* Pour le choix entre les trois, lisez les échanges sur le forum ci-dessous.
Un étudiant a écrit :
Bonjour, J'ai un problème concernant la fonction HashMap En effet, j'ai voulu créer une HashMap liant à chaque nom de room (tel que "entrance") la room qui lui correpondait. Pour cela, j'ai crée la Hashmap de cette façon : private HashMap<String, Room> aRoom; ainsi qu'un tableau de Room de cette façon : private Room[] aAllRooms = new Room[14]; // j'ai 14 rooms J'ai rangé mes rooms dans ce dernier dans la procédure createRooms, puis j'ai configuré leurs sorties. Jusque là je n'avais pas de problème Cependant, le problème arrive lorsque j'essaye d'initialiser la map. En effet, lorsque j'associe un String à une Room de cette façon : aRoom.put("entrance", aAllRooms[0]); le programme compile bien, mais lorsque je lance le jeu, il s'arrête tous de suite en me renvoyant à la ligne ci-dessus avec comme message d'erreur "java.lang.NullPointerException: null" Cependant je ne vois pas ce qui est vide (null) : le tableau aAllRooms[] est plein car je m'en suis servi pour configurer les Exits, et je suis en train de remplir aRoom qui a été initialisé. Cherchant à contourner le problème, j'ai trouvé sur Internet (oui je sais ...) un guide qui rajoutais "naturellement", dans la déclaration de sa HashMap, "= new HashMap();", ce qui donnait pour moi : private HashMap<String, Room> aRoom = new HashMap(); Ce qui a réglé mon problème, ou presque, car au moment de la compilation j'ai eu droit au message d'alerte suivant : "Warnings from last compilation D:\******\Documents\ESIEE\A3P\Catchim\Game.java uses unchecked or unsafe operations. Recompile with -Xlint unchecked for details." Après avoir cliqué Ok, je peux créer mon jeu, qui marche. Que dois-je faire ? Y a-t-il une autre solution ? Sinon, comment régler cette erreur ? Merci d'avance !
1) "J'ai un problème concernant la fonction HashMap"
HashMap n'est pas une fonction, mais une classe.
2) "Pour cela, j'ai crée la Hashmap de cette façon ... ainsi qu'un tableau de Room de cette façon ..."
Pourquoi créer les deux ? Comme dit dans l'énoncé, vous pouvez employer l'une ou l'autre de ces 2 solutions.
3) private HashMap<String,Room> aRoom; :
Très mauvais nom pour une variable qui va désigner plusieurs objets ! aRooms serait déjà mieux ...
4) L'instruction aRoom.put("entrance", aAllRooms[0]); provoque une
NullPointerException.
"Cependant je ne vois pas ce qui est vide (null)"
Comme expliqué dans le cours et dans l'atelier de débogage, la première chose qui peut valoir null ici, c'est aRoom !
C'est pour cela que vous n'avez pas le droit d'appeler la méthode put.
Il faut donc initialiser aRoom (comme n'importe quel attribut) en créant l'objet HashMap que vous n'avez pas créé, mais pour lequel vous avez simplement déclaré (et non initialisé) une référence.
5) "Cherchant à contourner le problème, j'ai trouvé sur Internet (oui je sais ...) un guide qui rajoutais "naturellement", dans la déclaration de sa HashMap, "= new HashMap();""
Effectivement, il vaut mieux appliquer les solutions expliquées en cours que n'importe quoi trouvé sur internet.
Que
voulez-vous dire par "naturellement" ? Nous n'avons JAMAIS initialisé
un attribut lors de sa déclaration et nous avons toujours expliqué que
l'initialisation d'un attribut se passait dans le constructeur.
Dans le cas présent, vu que le constructeur délègue la majeure partie de son travail à la procédure createRooms, cela nous fait une 2ème place possible pour l'initialisation de aRoom.
6) "Warnings from last compilation ... uses unchecked or unsafe operations."
C'est parce que vous créez une HashMap sans préciser le type des clés et le type des valeurs entre < et >.
Bonjour Monsieur Bureau,
Afin d'anticiper les futures modifications du projet j'aurais aimé savoir quelle solution entre le tableau et la HashMap semble convenir le mieux selon vous bien que vous nous informiez qu'on peut utiliser les deux.
Dans le sens où le tableau (ou la ArrayList) n'aura que des indices d'objets Room pour accéder aux éléments Room de ce dernier tandis que la HashMap peut en revanche fournir la Room (key) correspondante à la String (value) du même nom (pratique selon moi car il n'est besoin de connaître l'indice de la Room ou de faire un test pour y accéder).
J'envisagerais donc de créer une HashMap mais HashMap me pose un problème pour l'instant car je ne sais pas s'il est nécessaire ni même utile de la déclarer en tant qu'attribut de la classe Room, et s'il est préférable de la déclarer en Static ou pas ? Merci d'avance pour votre réponse.
Cordialement, Andrea Pancrazi.
1)
Vous avez vraiment le choix entre tableau, ArrayList et HashMap.
Il est probable que lors d'une utilisation l'un soit plus pratique, et
lors d'une autre utilisation, un autre soit plus pratique.
Maintenant, si votre scénario prévoit de pouvoir ajouter des lieux en cours de jeu, le tableau ne convient plus.
2)
Par contre, il n'y a aucune différence de déclaration, initialisation, remplissage, quel que soit votre choix.
Le/la déclarer en attribut ou en local dépendra d'où vous en aurez besoin, et peut toujours se modifier ... en cas de besoin.
Le/la déclarer en static est un peu contradictoire avec le fait de pouvoir créer des objets Game.
Un étudiant a écrit :
j'ai réussi à mettre la HashMap avec toutes mes Rooms et tout marche
correctement
hors je ne comprends pas comment on peut accéder à cette
HashMap en dehors de la class game étant donné qu'elle est privée.
Un étudiant a écrit :
Bonjour monsieur,
J'avais mis sur ma "ToDoList" qu'il fallait que je tente de revenir à cet exercice pour faire quelque chose mieux que 10 lignes de "this.aRooms.put(...)"
Je pensais donc à ceci :
-Créer un accesseur de aRooms public dans Game
- utiliser cet accesseur dans e constructeur Room(). Ainsi, à chaque création de Room, la Room créée pourrait directement s'ajouter à aRooms.
Seulement pour faire ainsi, j'ai un soucis : puis-je récupérer le nom de la Room que je suis en train de créer dans Room() ?
Je
m'explique : Si je créer une Room : Room rMainEntrance = new Room("u r
in Main Entrance"), puis-je récupérer le nom rMainEntrance dans mon
constructeur Room() ?
Vous devrez passer en paramètre du constructeur de Room la référence de Game. Par exemple,
Room vR1 = new Room(this,"1");
Bien entendu, le setter dans Game, connaissant la Room en train de s'initialiser, n'aura pas grande difficulté à accéder à la description de ladite Room pour effectuer le put dans la HashMap aRooms de Game.
Votre souci est étrange : par essence même, le constructeur de Room a accès à la description de la Room !
La solution que vous voulez développer est, je crois, originale et élégante.
Ecrivez-moi directement si vous ne parvenez pas à la mettre au point.
Je crois comprendre que vous souhaiteriez accéder au nom de la Room,
et pas seulement à sa description, ce qui ne sera effectivement pas possible en dehors de createRooms,
même avec la solution ci-dessus.
Aussi, je vous propose de prendre les choses dans l'autre sens :
imaginez une fonction qui vous retourne la Room
qu'elle viendrait de créer, tout en l'ayant ajouté au passage à this.aRooms,
puis remplacez dans createRooms
les new par des appels à cette fonction, en lui passant ce fameux nom.
Réseaux sociaux